home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2007 September / PCWSEP07.iso / Software / Linux / Linux Mint 3.0 Light / LinuxMint-3.0-Light.iso / casper / filesystem.squashfs / usr / share / onboard / Keyboard.py < prev    next >
Encoding:
Python Source  |  2007-02-20  |  8.9 KB  |  355 lines

  1. #!/usr/bin/python
  2.  
  3. import gtk
  4. import Key
  5. import gobject
  6. import gconf
  7. import string
  8. from Key import *
  9. sidebarWidth = 60
  10. try:
  11.     from utils import run_script 
  12.     from utils import keysyms
  13. except DeprecationWarning:
  14.     pass
  15.  
  16.  
  17. class Keyboard(gtk.DrawingArea):
  18.     "Cairo based keyboard widget"
  19.     def __init__(self,sok,basePane,panes):
  20.         gtk.DrawingArea.__init__(self)
  21.  
  22.         self.add_events(gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK | gtk.gdk.LEAVE_NOTIFY_MASK) 
  23.         self.connect("expose_event", self.expose)
  24.         self.connect("button_press_event", self.mouse_button_press)
  25.         self.connect("button_release_event", self.mouse_button_release)
  26.         self.connect("leave-notify-event", self.cb_leave_notify)
  27.     
  28.     self.sok = sok
  29.     
  30.     self.activePane = None # When set to a pane, the pane overlays the basePane.
  31.         
  32.     self.active = None #Currently active key
  33.         
  34.         self.scanningActive = None # Key currently being scanned.
  35.         
  36.     self.stuck = [] #List of keys which have been latched.  ie. pressed until next non sticky button is pressed.
  37.     
  38.     self.altLocked = False 
  39.  
  40.     self.tabKeys = []
  41.     
  42.     self.basePane = basePane #Pane which is always visible
  43.     
  44.     self.panes = panes # All panes except the basePane
  45.  
  46.     self.tabKeys.append(BaseTabKey(self,sidebarWidth))
  47.  
  48.     if self.panes:
  49.         for n in range(len(self.panes)):
  50.                     self.tabKeys.append(TabKey(self,sidebarWidth,self.panes[n]))
  51.         
  52.         self.queue_draw()
  53.         
  54.         
  55.     def cb_leave_notify(self, widget, grabbed):
  56.         gtk.gdk.pointer_ungrab() # horrible.  Grabs pointer when key is pressed, released when cursor leaves keyboard
  57.     if self.active:
  58.                 
  59.         if self.scanningActive:
  60.             self.active = None        
  61.             self.scanningActive = None
  62.         else:        
  63.             self.release_key(self.active)
  64.         self.queue_draw()
  65.     return True
  66.     
  67.     
  68.     def utf8_to_unicode(self,utf8Char):
  69.         
  70.         return ord(utf8Char.decode('utf-8'))
  71.       
  72.         
  73.     def scan_tick(self): #at intervals scans across keys in the row and then down columns.
  74.         if self.scanningActive:
  75.             self.scanningActive.beingScanned = False
  76.         
  77.         if self.activePane:
  78.             pane = self.activePane
  79.         else:
  80.             pane = self.basePane
  81.         
  82.         if not self.sok.scanningNoY == None:
  83.             self.sok.scanningNoY = (self.sok.scanningNoY + 1) % len(pane.columns[self.sok.scanningNoX])
  84.         else:
  85.             self.sok.scanningNoX = (self.sok.scanningNoX + 1) % len(pane.columns)
  86.         
  87.         if self.sok.scanningNoY == None:
  88.             y = 0
  89.         else:
  90.             y = self.sok.scanningNoY
  91.         
  92.         self.scanningActive = pane.columns[self.sok.scanningNoX][y]
  93.         
  94.         self.scanningActive.beingScanned = True
  95.      self.queue_draw()
  96.         
  97.         return True
  98.         
  99.     
  100.     def reset_scan(self):#Between scans and when value of scanning changes.
  101.         
  102.         if self.scanningActive:
  103.             self.scanningActive.beingScanned = False
  104.         
  105.         self.sok.scanningTimeId = None
  106.             
  107.             self.sok.scanningNoX = None
  108.             self.sok.scanningNoY = None
  109.             self.queue_draw()
  110.         
  111.     def mouse_button_press(self,widget,event):
  112.         gtk.gdk.pointer_grab(self.window, True)
  113.         if event.type == gtk.gdk.BUTTON_PRESS:
  114.         self.active = None#is this doing anything
  115.             
  116.             if self.sok.scanning and self.basePane.columns:
  117.                 
  118.                 if self.sok.scanningTimeId:
  119.                     if not self.sok.scanningNoY == None:
  120.                         self.press_key(self.scanningActive)
  121.                         gobject.source_remove(self.sok.scanningTimeId)
  122.                         self.reset_scan()
  123.                         
  124.                         
  125.                     else:
  126.                         self.sok.scanningNoY = -1
  127.                         gobject.source_remove(self.sok.scanningTimeId)
  128.                         self.sok.scanningTimeId = gobject.timeout_add(self.sok.scanningInterval,self.scan_tick)
  129.                 else:    
  130.                     self.sok.scanningTimeId = gobject.timeout_add(self.sok.scanningInterval,self.scan_tick)
  131.                     self.sok.scanningNoX = -1
  132.             else:
  133.                     
  134.             if self.activePane:
  135.                 for key in self.activePane.keys.values():
  136.                     self.is_key_pressed(key,event)
  137.             else:    
  138.                 for key in self.basePane.keys.values():
  139.                     self.is_key_pressed(key,event)
  140.             
  141.  
  142.             for key in self.tabKeys:
  143.                 self.is_key_pressed(key,event)
  144.     return True 
  145.  
  146.      
  147.     def is_key_pressed(self,key,event):
  148.         if(key.point_within_key(event.x,event.y)):
  149.             self.press_key(key)
  150.     
  151.     def mouse_button_release(self,widget,event):
  152.     
  153.     if self.active:
  154.         self.active.on = False
  155.         self.release_key(self.active)
  156.         if len(self.stuck) > 0:
  157.             for stick in self.stuck:
  158.                 self.release_key(stick)
  159.             self.stuck = []
  160.         self.active = None
  161.  
  162.     self.queue_draw()
  163.     return True
  164.  
  165.     def press_key(self,key):
  166.         if not key.on:
  167.         
  168.         if self.sok.mods[8]:
  169.             self.altLocked = True
  170.             self.sok.vk.lock_mod(8)    
  171.  
  172.         if key.sticky == True:
  173.                 self.stuck.append(key)
  174.                 
  175.         else:
  176.             self.active = key #Since only one non-sticky key can be pressed at once.
  177.         
  178.         key.on = True
  179.         
  180.         self.locked = []
  181.         
  182.         
  183.         
  184.             if key.actions[0]:
  185.             self.sok.vk.press_unicode(self.utf8_to_unicode(key.actions[0]))
  186.         
  187.         elif key.actions[2]:
  188.             self.sok.vk.press_keysym(keysyms[key.actions[2]])
  189.         
  190.         elif key.actions[1]:
  191.             self.sok.vk.press_keysym(key.actions[1])
  192.         
  193.         elif key.actions[3]:
  194.             
  195.             mod = key.actions[3]
  196.             
  197.             if not mod == 8: #Hack since alt puts metacity into move mode and prevents clicks reaching widget.
  198.                 self.sok.vk.lock_mod(mod)
  199.             self.sok.mods[mod] += 1
  200.                 
  201.  
  202.         elif key.actions[4]:#macros
  203.              try:
  204.                 mString = self.sok.macros[string.atoi(key.actions[4])]
  205.                 if mString:#If mstring exists do the below, otherwise the code in finally should always be done.
  206.                     for c in mString:
  207.                         char = self.utf8_to_unicode(c)
  208.                         self.sok.vk.press_unicode(char)
  209.                         self.sok.vk.release_unicode(char)
  210.                     return
  211.                         
  212.             except IndexError:
  213.                 pass
  214.  
  215.             dialog = gtk.Dialog("No snippet", self.sok.window, 0, ("_Save snippet", gtk.RESPONSE_OK, 
  216.                                     "_Cancel", gtk.RESPONSE_CANCEL))
  217.             dialog.vbox.add(gtk.Label("No snippet for this button,\nType new snippet"))
  218.             
  219.             macroEntry = gtk.Entry()                
  220.         
  221.             dialog.connect("response", self.cb_dialog_response,string.atoi(key.actions[4]), macroEntry)
  222.             
  223.             macroEntry.connect("activate", self.cb_macroEntry_activate,string.atoi(key.actions[4]), dialog)
  224.             dialog.vbox.pack_end(macroEntry)
  225.  
  226.             dialog.show_all()
  227.  
  228.  
  229.         elif key.actions[5]:
  230.             run_script(key.actions[5],self.sok)    
  231.             
  232.         else:
  233.             for k in self.tabKeys: # don't like this.
  234.                 if k.pane == self.activePane:
  235.                     k.on = False
  236.                     k.stuckOn = False
  237.             
  238.             self.activePane = key.pane
  239.         
  240.                     
  241.  
  242.     else:
  243.         if key in self.stuck:
  244.             key.stuckOn = True
  245.             self.stuck.remove(key)
  246.         else:
  247.             key.stuckOn = False
  248.             self.release_key(key)
  249.  
  250.     self.queue_draw()
  251.         
  252.         
  253.     def cb_dialog_response(self, widget, response, macroNo,macroEntry):
  254.     self.set_new_macro(macroNo, response, macroEntry, widget)
  255.  
  256.     def cb_macroEntry_activate(self,widget,macroNo,dialog):
  257.     self.set_new_macro(macroNo, gtk.RESPONSE_OK, widget, dialog)
  258.     
  259.         
  260.  
  261.     def set_new_macro(self,macroNo,response,macroEntry,dialog):
  262.     if response == gtk.RESPONSE_OK:    
  263.         
  264.         if macroNo > (len(self.sok.macros) - 1):#makes sure array long enough for this next bit
  265.             for n in range((macroNo + 1) - len(self.sok.macros)):            
  266.                 self.sok.macros.append("")
  267.         
  268.         self.sok.macros[macroNo] = macroEntry.get_text()
  269.         self.sok.gconfClient.set_list("/apps/sok/macros",gconf.VALUE_STRING, self.sok.macros)
  270.  
  271.     dialog.destroy()
  272.     
  273.     
  274.  
  275.     def release_key(self,key):
  276.         key.on = False
  277.     
  278.     
  279.  
  280.         if key.actions[0]:
  281.             self.sok.vk.release_unicode(self.utf8_to_unicode(key.actions[0]))
  282.     elif key.actions[2]:
  283.         self.sok.vk.release_keysym(keysyms[key.actions[2]])
  284.     elif key.actions[1]:
  285.         self.sok.vk.release_keysym(key.actions[1])
  286.     elif key.actions[3]:
  287.         mod = key.actions[3]
  288.         
  289.         if not mod == 8:        
  290.             self.sok.vk.unlock_mod(mod)
  291.         
  292.         self.sok.mods[mod] -= 1
  293.         
  294.         #if not self.sok.mods[mod]: #if the modifier is currently pressed globaly.
  295.         #    self.sok.vk.unlock_mod(mod)
  296.     elif key.actions[4] or key.actions[5]:
  297.         pass
  298.             
  299.             
  300.     else:
  301.         self.activePane = None
  302.     
  303.     
  304.     if self.altLocked:
  305.         self.altLocked = False
  306.         self.sok.vk.unlock_mod(8)
  307.         
  308.  
  309.           
  310.     
  311.     def expose(self, widget, event):
  312.         
  313.         context = widget.window.cairo_create()
  314.         context.set_line_width(1.1)
  315.         
  316.         size = self.get_allocation()
  317.         
  318.             self.kbwidth = size.width - sidebarWidth # to allow for sidebar
  319.         self.height = size.height
  320.         
  321.         context.set_source_rgba(float(self.basePane.rgba[0]),
  322.                     float(self.basePane.rgba[1]),
  323.                     float(self.basePane.rgba[2]),
  324.                     float(self.basePane.rgba[3]))#get from .sok
  325.         context.paint()
  326.         
  327.         
  328.         self.basePane.paint(context,self.kbwidth,self.height)
  329.         
  330.         if (self.activePane):
  331.         
  332.         context.rectangle(0, 0, self.kbwidth, self.height)
  333.         context.set_source_rgba(float(self.activePane.rgba[0]),
  334.                     float(self.activePane.rgba[1]),
  335.                     float(self.activePane.rgba[2]),
  336.                     float(self.activePane.rgba[3]))#get from .sok
  337.             context.fill()
  338.         self.activePane.paint(context,self.kbwidth,self.height)
  339.         
  340.             
  341.             
  342.             for key in self.tabKeys:
  343.                 key.paint(context)
  344.         
  345.             return True
  346.  
  347.  
  348.     
  349.  
  350.         
  351.  
  352.  
  353.     
  354.  
  355.